<?php

namespace App\Http\Middleware;

use App\Exceptions\Code\ErrorCode;
use App\Exceptions\JsonResponse\JsonResponseException;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * 加解密
 *
 * Class Des
 *
 * @package App\Http\Middleware
 */
class Des
{
    public $desKey;
    public $desIv;

    public function __construct()
    {
        $this->desKey = config('des.key');
        $this->desIv = config('des.iv');
    }

    /**
     * 跳过加密
     * @var bool
     */
    public $skipEncryption = false;

    /**
     * 是否跳过加密
     * @param $request
     * @return bool
     */
    protected function getSkipDes(Request $request)
    {
        if (config('des.request_debug')) {
            if ($request->header('Des-Debug') == '1' || $request->input('debug') == 1) {
                return true;
            }
        }
        return false;
    }

    /**
     * 解密
     * @param Request $request
     */
    protected function decrypt(Request $request)
    {
        if (!$this->skipEncryption) {
            if (!$request->has('data')) {
                throw new JsonResponseException("", ErrorCode::DATA_MISSING);
            }
            $data = $request->input('data');
            try {
                $data = json_decode(des_decrypt($data, $this->desKey, $this->desIv), true);
                foreach ($data as $key => $value) {
                    $request->merge([$key => $value]);//添加参数
                }
            } catch (\Throwable $t) {
                throw new JsonResponseException("", ErrorCode::DECRYPT_FAILED);
            }
        }
    }

    /**
     * 加密
     * @param Response $response
     */
    protected function encryption(Response $response)
    {
        $content = $response->getContent();
        if (!$response instanceof BinaryFileResponse) {
            $response->setContent(des_encrypt($content, $this->desKey, $this->desIv));
        }
    }

    /**
     * @param $request
     * @param Closure $next
     * @return mixed|Response
     * @throws \Throwable
     */
    public function handle($request, Closure $next)
    {
        $skipDes = $this->getSkipDes($request);
        if (!$skipDes) {
            $this->decrypt($request);
        }
        $response = $next($request);
        if (!$skipDes) {
            $this->encryption($response);
        }
        return $response;
    }
}
